<?php


namespace NanQi\Hope\Db;


use Hyperf\Utils\Str;

class EsModel
{
    protected $index;

    /**
     * 索引设置
     * @var array
     */
    protected $setting = [
        'number_of_shards'   => 2,
        'number_of_replicas' => 0
    ];
    /**
     * 索引参数
     * @var array
     */
    protected $properties = [];
    /**
     * @var int 搜索结果总数
     */
    protected $count = 0;
    /**
     * @var array query返回的查询结果
     */
    protected $origin_data;

    public static function single()
    {
        $model = new static();
        return $model;
    }

    public function getIndex()
    {
        if (!$this->index) {
            $className = class_basename($this);
            if (Str::endsWith($className, 'EsModel')) {
                $className = Str::substr($className, 0, strlen($className) - 7);
            }

            $index = Str::snake($className);
            if (!Str::endsWith($index, '_index')) {
                $index .= '_index';
            }

            $this->index = $index;
        }
        return $this->index;
    }

    /**
     * newQuery
     * @return EsQuery
     */
    protected function newQuery()
    {
        return new EsQuery($this);
    }

    /**
     * query
     * @return EsQuery
     */
    public static function query()
    {
        return (new static)->newQuery();
    }


    /**
     * 创建索引
     * @return array
     */
    public static function createIndex()
    {
        $model = static::single();
        $params = [
            'index' => $model->getIndex(),
            'body'  => [
                'settings' => $model->setting
            ]
        ];
        return Es::getClient()->indices()->create($params);
    }

    /**
     * 是否存在索引
     * @return bool
     */
    public static function existsIndex() : bool
    {
        $model = static::single();
        $params = [
            'index' => $model->getIndex(),
        ];
        return Es::getClient()->indices()->exists($params);
    }

    /**
     * deleteIndex
     * @return array
     */
    public static function deleteIndex()
    {
        $model = static::single();
        $delete_params = [
            'index' => $model->getIndex()
        ];
        return Es::getClient()->indices()->delete($delete_params);
    }

    /**
     * __callStatic
     * @param $func
     * @param $params
     * @return EsQuery
     */
    public static function __callStatic($func, $params)
    {
        $query = static::query();
        return $query->$func(...$params);
    }

    /**
     * 添加文档
     * @param $data
     * @param $id
     * @return array|bool
     */
    public static function add($data, $id = '')
    {
        $model = static::single();

        $params = [
            'index' => $model->getIndex(),
            'body'  => $data
        ];

        if ($id) {
            $params['id'] = $id;
        }
        $re = Es::getClient()->index($params);
        return $re;
    }

    public static function update($id, $data)
    {
        $model = static::single();
        $re = Es::getClient()->update([
            'index' => $model->getIndex(),
            'id'    => $id,
            'body'  => ['doc' => $data]
        ]);
        return $re;
    }

    public static function exists($id) : bool
    {
        try {
            $model = static::single();
            $data = Es::getClient()->exists([
                'index' => $model->getIndex(),
                'id'    => $id
            ]);
            return $data;
        } catch (\Exception $e) {
            return false;
        }
    }

    public static function delete($id)
    {
        try {
            $model = static::single();
            $data = Es::getClient()->delete([
                'index' => $model->getIndex(),
                'id'    => $id
            ]);
            return $data;
        } catch (\Exception $e) {
            return false;
        }
    }

    public static function find($id)
    {
        $model = static::single();
        $data = Es::getClient()->getSource([
            'index' => $model->getIndex(),
            'id'    => $id
        ]);
        return $data;
    }

    /**
     * @param $result
     * @return EsModel $this
     */
    public function setData($result) : EsModel
    {
        $this->origin_data = $result['source'];
        if (isset($result['total'])) {
            $this->count = $result['total'];
        }
        return $this;
    }

    public function getData()
    {
        return $this->origin_data;
    }

    public function getCount()
    {
        return $this->count;
    }

    public function __toString()
    {
        return json_encode($this->origin_data);
    }
}